package com.sdp.core.bizc.db;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdp.core.bizc.annotation.ViewColumn;
import com.sdp.core.bizc.exception.ApplicationException;
import com.sdp.core.bizc.exception.ExceptionMessage;
import com.sdp.core.bizc.utils.CoreConstantsEnum;
import com.sdp.core.bizc.vo.DataCenter;

@Component
public class Query {
	
	/**
	 * 分页查询
	 * @param service
	 * @param dc
	 * @param queryWrapper
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T>IPage<T> page(@SuppressWarnings("rawtypes") IService service,DataCenter dc,QueryWrapper<T> queryWrapper) {
		Page<T> page = new Page<T>(dc.getPageNo(), dc.getPageSize());
		IPage<T> pageList = service.page(page, queryWrapper);
		if(pageList.getPages()>0 && pageList.getCurrent()>pageList.getPages()) {
			//防止出现，数据库删除了记录，前台传入的页码大于总页码
			page.setCurrent(pageList.getPages());
			pageList = service.page(page, queryWrapper);
		}
		return pageList;
	}
	
	/**
	 * 封装的根据实体，条件进行分页查询
	 * @param mapper
	 * @param systemNo
	 * @param clazz
	 * @param dc
	 * @param queryWrapper
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T>IPage<T> page(@SuppressWarnings("rawtypes") IService service,Class<T> clazz,DataCenter dc,QueryWrapper<T> queryWrapper) {
		Page<T> page = new Page<T>(dc.getPageNo(), dc.getPageSize());
		IPage<T> pageList = service.page(page, initQueryWrapper(clazz, dc,queryWrapper));
		if(pageList.getPages()>0 && pageList.getCurrent()>pageList.getPages()) {
			//防止出现，数据库删除了记录，前台传入的页码大于总页码
			page.setCurrent(pageList.getPages());
			pageList = service.page(page, initQueryWrapper(clazz, dc,queryWrapper));
		}
		
		return pageList;
	}
	
	
	public <T>IPage<T> page(@SuppressWarnings("rawtypes") IService service,Class<T> clazz,DataCenter dc) {
		return page(service, clazz, dc,null);
	}


	

	
	/**
	 * 封装的根据实体，模块，条件进行不分页查询
	 * @param mapper
	 * @param systemNo
	 * @param clazz
	 * @param dc
	 * @param queryWrapper
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T>List<T> list(@SuppressWarnings("rawtypes") IService service,Class<T> clazz,DataCenter dc,QueryWrapper<T> queryWrapper) {
		return service.list(initQueryWrapper(clazz, dc,queryWrapper));
	}
	
	public <T>List<T> list(@SuppressWarnings("rawtypes") IService service,Class<T> clazz,DataCenter dc) {
		return list(service, clazz, dc, null);
	}

	
	/**
	 * 封装的查询记录数
	 * @param mapper
	 * @param systemNo
	 * @param clazz
	 * @param dc
	 * @param queryWrapper
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> int count(@SuppressWarnings("rawtypes") IService service,Class<T> clazz,DataCenter dc,QueryWrapper<T> queryWrapper) {
	
		if (dc!=null && dc.getSelectColumns() != null) {
			queryWrapper.select(dc.getSelectColumns());
		}
		Field[] fields = clazz.getDeclaredFields();
		Map<String, Field> fieldMap = new HashMap<>();
		for (Field field : fields) {
			fieldMap.put(field.getName(), field);
		}

		initQueryForm(fieldMap, queryWrapper, dc);
		
		return service.count(queryWrapper);
	}
	
	public <T> int count(@SuppressWarnings("rawtypes") IService service,Class<T> clazz,DataCenter dc) {
		QueryWrapper<T> queryWrapper = new QueryWrapper<T>();
		return count(service, clazz, dc,queryWrapper);
	}
	
	
	
	
	/**
	 * 封装初始化查询条件
	 * @param systemNo
	 * @param clazz
	 * @param dc
	 * @param queryWrapper
	 * @return
	 */
	public <T> QueryWrapper<T> initQueryWrapper(Class<T> clazz,DataCenter dc,QueryWrapper<T> queryWrapper){
		if(queryWrapper==null) {
			queryWrapper = new QueryWrapper<T>();
		}

		if (dc!=null && dc.getSelectColumns() != null) {
			queryWrapper.select(dc.getSelectColumns());
		}
		Field[] fields = clazz.getDeclaredFields();
		Map<String, Field> fieldMap = new HashMap<>();
		for (Field field : fields) {
			fieldMap.put(field.getName(), field);
		}

		initQueryForm(fieldMap, queryWrapper, dc);
		initQueryOrder(fieldMap, queryWrapper, dc);
		return queryWrapper;
	}
	
	
	private void initQueryForm(Map<String, Field> fieldMap,QueryWrapper<?> queryWrapper,DataCenter dc) {
		if(dc==null) {
			return;
		}
		List<QueryColumn> queryParas = dc.getQueryForm();
		if(queryParas==null || queryParas.size()==0) {
			return;
		}
		Field field;
		TableField tableField;
		String rule;
		try {
			for(QueryColumn qc : queryParas) {
				field = fieldMap.get(qc.getField());
				tableField = field.getAnnotation(TableField.class);
				if(tableField!=null) {
					if(!StringUtils.isEmpty(qc.getCondition())) {
						rule = qc.getCondition();
					}else {
						rule = QueryRuleEnum.EQ.getCode();
					}
					QueryUtil.addQueryByRule(queryWrapper, rule, tableField.value(), field.getType().toString(), qc.getVal());
				}
				
			}
			
		} catch (Exception e) {
			throw new ApplicationException(ExceptionMessage.getExceptionMessage(e));
		}
		
	}
	
	private void initQueryOrder(Map<String, Field> fieldMap,QueryWrapper<?> queryWrapper,DataCenter dc) {
		if(dc==null) {
			return;
		}
		List<QueryColumn> queryOrders = dc.getOrderColumns();
		if(queryOrders==null || queryOrders.size()==0) {
			return;
		}
		Field field;
		TableField tableField;
		String desc="DESC";
		String asc ="ASC";
		try {
			for(QueryColumn qc : queryOrders) {
				field = fieldMap.get(qc.getField());
				tableField = field.getAnnotation(TableField.class);
				if(tableField!=null && !StringUtils.isEmpty(qc.getVal())) {
					if((qc.getVal().toUpperCase()).indexOf(desc)>=0){
						queryWrapper.orderByDesc(tableField.value());
					}else if((qc.getVal().toUpperCase()).indexOf(asc)>=0) {
						queryWrapper.orderByAsc(tableField.value());
					}
				}
			}
			
		} catch (Exception e) {
			throw new ApplicationException(ExceptionMessage.getExceptionMessage(e));
		}
	}
	
	
	//视图处理
	public <T> IPage<T> viewPage(IViewQuery service, Class<T> clazz, DataCenter dc, QueryWrapper<T> queryWrapper) {
		Page<T> page = new Page<T>(dc.getPageNo(), dc.getPageSize());
		initViewQueryWrapper(clazz, queryWrapper, dc);
		IPage<T> pageList = service.viewPage(page, queryWrapper,dc);
		if (pageList.getPages()>0 && pageList.getCurrent()>pageList.getPages()) {
			//防止出现，数据库删除了记录，前台传入的页码大于总页码
			page.setCurrent(pageList.getPages());
			pageList = service.viewPage(page, queryWrapper,dc);
		}
		return pageList;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> viewList(IViewQuery service, Class<T> clazz, DataCenter dc, QueryWrapper<?> queryWrapper) {
		initViewQueryWrapper(clazz, queryWrapper, dc);
		return (List<T>) service.viewList(queryWrapper,dc);
	}
	
	public <T> int viewCount(IViewQuery service, Class<T> clazz, DataCenter dc, QueryWrapper<?> queryWrapper) {
		initViewQueryWrapper(clazz, queryWrapper, dc);
		return service.viewCount(queryWrapper);
	}
	
	public <T> void initViewQueryWrapper(Class<T> clazz, QueryWrapper<?> queryWrapper, DataCenter dc) {
		//根据queryFORM 生成查询条件
		Field[] fields = clazz.getDeclaredFields();
		Map<String, Field> fieldMap = new HashMap<>();
		for (Field field : fields) {
			fieldMap.put(field.getName(), field);
		}
		//根据queryFORM 生成查询条件
		initViewQueryForm(fieldMap, queryWrapper, dc);
		//构造排序
		initViewOrder(fieldMap, queryWrapper, dc);
	}
	
	private <T>void initViewQueryForm(Map<String, Field> fieldMap, QueryWrapper<?> queryWrapper, DataCenter dc) {
		if(dc==null) {
			return;
		}
		List<QueryColumn> queryParas = dc.getQueryForm();
		if(queryParas==null || queryParas.size()==0) {
			return;
		}
		Field field;
		ViewColumn column;
		String rule;
		try {
			for(QueryColumn qc : queryParas) {
				field = fieldMap.get(qc.getField());
				if (field != null && field.isAnnotationPresent(ViewColumn.class)) {
					column = field.getAnnotation(ViewColumn.class);
					if(!StringUtils.isEmpty(qc.getCondition())) {
						rule = qc.getCondition();
					}else {
						rule = QueryRuleEnum.EQ.getCode();
					}
					QueryUtil.addQueryByRule(queryWrapper, rule, column.value(), field.getType().toString(), qc.getVal());
				}
			}
		} catch (Exception e) {
			throw new ApplicationException("##############解析queryform查询条件字段错误！", e);
		}
	}
	
	private <T>void initViewOrder(Map<String, Field> fieldMap, QueryWrapper<T> queryWrapper, DataCenter dc) {
		if(dc==null) {
			return;
		}
		List<QueryColumn> queryOrders = dc.getOrderColumns();
		if(queryOrders==null || queryOrders.size()==0) {
			return;
		}
		Field field;
		ViewColumn column;
		String desc="DESC";
		String asc ="ASC";
		try {
			for(QueryColumn qc : queryOrders) {
				field = fieldMap.get(qc.getField());
				if (field != null && field.isAnnotationPresent(ViewColumn.class)) {
					column = field.getAnnotation(ViewColumn.class);
					if(!StringUtils.isEmpty(qc.getVal())) {
						if((qc.getVal().toUpperCase()).indexOf(desc)>=0){
							queryWrapper.orderByDesc(column.value());
						}else if((qc.getVal().toUpperCase()).indexOf(asc)>=0) {
							queryWrapper.orderByAsc(column.value());
						}
						
					}
				}
			}
		} catch (Exception e) {
			throw new ApplicationException(ExceptionMessage.getExceptionMessage(e));
		}
	}
	
	/**
	 * 生成表格树
	 * @param records
	 * @param parentField
	 * @return
	 */
	public List<JSONObject> tableTree(List<?>records,String parentField) {
		List<JSONObject> treeList = new ArrayList<JSONObject>();
		List<Object> rootList = new ArrayList<>();
		Object record = null;
		String parentVal=null;
		try {
			for(int i=0;i<records.size();i++) {
				record = records.get(i);
				Class<?> clazz = record.getClass();
				Field field = clazz.getDeclaredField(parentField);
				field.setAccessible(true);
				parentVal = (String) field.get(record);
				if(StringUtils.isEmpty(parentVal) || CoreConstantsEnum.否.getCode().equals(parentVal)) {
					rootList.add(record);
				}
			}
			
			if(rootList==null || rootList.size()==0) {
				return treeList;
			}
			JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
			JSONObject parentObj =null;
			for(int i=0;i<rootList.size();i++) {
				parentObj = JSON.parseObject(JSON.toJSONStringWithDateFormat(rootList.get(i), "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat));
				treeList.add(parentObj);
				tableTreeChild(parentObj, records,parentField);
			}
			
		} catch (Exception e) {
			throw new ApplicationException(ExceptionMessage.getExceptionMessage(e));
		}
		
		return treeList;
	}
	
	@SuppressWarnings("unchecked")
	private void tableTreeChild(JSONObject parentObj,List<?> records,String parentField) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		List<Object> childList = new ArrayList<Object>();
		Object record = null;
		String parentVal=null;
		for(int j=0;j<records.size();j++) {
			record = records.get(j);
			Class<?> clazz = record.getClass();
			Field field = clazz.getDeclaredField(parentField);
			field.setAccessible(true);
			parentVal = (String) field.get(record);
			
			if(!StringUtils.isEmpty(parentVal) && parentObj.getString("keyId").equals(parentVal)) {
			
				if(parentObj.get("children")==null) {
					parentObj.put("children", childList);
				}else {
					childList = (List<Object>) parentObj.get("children");
				}
				JSONObject childObj = JSON.parseObject(JSON.toJSONStringWithDateFormat(records.get(j),"yyyy-MM-dd HH:mm:ss",SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat).toString());
				childList.add(childObj);
				tableTreeChild(childObj, records,parentField);
			}
			
		}
	}
	
}
